home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / tutor / asm1tut.exe / CHAP6.DOC < prev    next >
Text File  |  1990-06-21  |  17KB  |  381 lines

  1.  
  2.  
  3.  
  4.                                                                             41
  5.  
  6.                           CHAPTER 6 - MULTIPLICATION AND DIVISION
  7.  
  8.  
  9.  
  10.              Unlike addition and subtraction, where the result can be in
  11.              either memory or in one of the registers, the multiplication and
  12.              division instructions have a rigid format. 
  13.  
  14.  
  15.              MULTIPLICATION
  16.  
  17.              You can multiply a one byte number by a one byte number and get a
  18.              two byte result, or you can multiply a one word number by a one
  19.              word number and get a two word result. The first number MUST be
  20.              in AL for the byte operation or in AX for the word operation. The
  21.              second number may be a register or a memory location (but not a
  22.              constant). The result is in AH:AL for the byte operation and
  23.              DX:AX for the word operation. Our possibilities are:
  24.  
  25.                       AL  X  (one byte register or memory)  ->  AH:AL
  26.                       AX  X  (one word register or memory)  ->  DX:AX
  27.  
  28.              Is there a difference between signed and unsigned numbers? Yes, a
  29.              very big difference. For the byte operation  FFh = -1 signed but
  30.              FFh = 255 unsigned.  -1 X -1 = 1 = 0001h.  255 X 255 = 65025 =
  31.              FE01h. These are two completely different answers. You need to
  32.              tell the 8086 whether you want signed multiplication or unsigned
  33.              multiplication. The 8086 does the rest. Let's look at both signed
  34.              and unsigned multiplication. We'll do byte multiplication for
  35.              unsigned numbers and word multiplication for signed numbers. The
  36.              instruction for unsigned multiplication is MUL. The instruction
  37.              for signed multiplication is IMUL. AX or AL is understood to be
  38.              the register, so it is not in the code. The instructions are:
  39.  
  40.                  variable1  db ?
  41.                  variable2  dw ?
  42.  
  43.                       mul  bx             ; unsigned word from a register
  44.                       mul  variable1      ; unsigned byte from memory
  45.                       imul ch             ; signed byte from a register
  46.                       imul variable2      ; signed word from memory
  47.  
  48.              No AX or AL. It's understood. Here's our program:
  49.  
  50.              template.asm
  51.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  52.              answer1      dw     ? 
  53.              answer2      dw     ? 
  54.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  55.  
  56.              ; - - - - - START CODE BELOW THIS LINE 
  57.               
  58.                     mov     cx, 0               ; clear cx for visual effect 
  59.  
  60.              ______________________
  61.  
  62.              The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
  63.  
  64.  
  65.  
  66.  
  67.              The PC Assembler Tutor                                         42
  68.              ______________________
  69.  
  70.               
  71.              outer_loop: 
  72.                     ; unsigned byte multiplication 
  73.                     mov   ax_byte, 0A2h          ; half regs, unsigned 
  74.                     mov   bx_byte, 0A2h          ; half regs, unsigned 
  75.                     lea   ax, ax_byte 
  76.                     call  set_reg_style 
  77.               
  78.                     mov   ax, 0               ; clear regs 
  79.                     mov   bx, 0 
  80.                     mov   dx, 0 
  81.                     call  show_regs 
  82.                      
  83.                     call  get_unsigned_byte    ; get two unsigned bytes
  84.                     call  show_regs 
  85.                     push  ax                   ; save the first number
  86.                     call  get_unsigned_byte 
  87.                     mov   bl, al 
  88.                     pop   ax                   ; restore the first number
  89.                     call  show_regs_and_wait 
  90.                     mul   bl                   ; unsigned multiplication
  91.                     call  print_unsigned       ; display the result (ax)
  92.                     call  show_regs_and_wait 
  93.                      
  94.               
  95.                     ; signed word multiplication 
  96.                     mov   ax_byte, 01h          ; full reg, signed 
  97.                     mov   bx_byte, 01h  
  98.                     mov   dx_byte, 01h
  99.                     lea   ax, ax_byte 
  100.                     call  set_reg_style 
  101.               
  102.                     mov   ax, 0               ; clear regs 
  103.                     mov   bx, 0 
  104.                     call  show_regs 
  105.               
  106.                     call  get_signed           ; get two numbers
  107.                     call  show_regs 
  108.                     push  ax                   ; save the first number
  109.                     call  get_signed 
  110.                     mov   bx, ax 
  111.                     pop   ax                   ; restore the first number
  112.                     call  show_regs_and_wait 
  113.                     imul  bx                   ; signed multiplication 
  114.                     push  ax                   ; save result
  115.                     mov   answer1, ax          ; display 4 byte result
  116.                     mov   answer2, dx 
  117.                     lea   ax, answer1 
  118.                     call  print_signed_4byte 
  119.                     pop   ax                   ; restore result
  120.                     call  show_regs_and_wait 
  121.               
  122.                    jmp    outer_loop 
  123.              ; - - - - - END CODE ABOVE THIS LINE 
  124.  
  125.              If the answer for the unsigned byte multiplication is greater
  126.              than 255, it will be difficult to read the answer from the half
  127.  
  128.  
  129.  
  130.  
  131.              Chapter 6 - Multiplication and Division                        43
  132.              _______________________________________
  133.  
  134.              registers, so we print out the whole AX register.
  135.  
  136.              If the answer for the signed word multiplication is greater than
  137.              +32767 or is less than -32768, the answer will be unreadable in
  138.              the DX:AX registers. We move the answer to memory, and then call
  139.              print_signed_4byte. As with set_reg_style, the data is too long
  140.              to be put in AX, so we pass the address of the first byte of
  141.              data with:
  142.  
  143.                  lea  ax, answer1
  144.  
  145.              and then call print_signed_4byte. Everything from PUSH AX to POP
  146.              AX is designed to do that.
  147.  
  148.              Do MUL and IMUL set any flags? Yes. For byte multiplication, if
  149.              AL contains the total answer, the 8086 clears the OF and CF
  150.              flags. If part of the answer is in AH, then the 8086 sets both
  151.              the OF and CF flags.  For word multiplication, if AX contains the
  152.              total answer, the 8086 clears the OF and CF flags. If part of the
  153.              answer is in DX, then the 8086 sets both the OF and CF flags. 
  154.  
  155.              What do we mean by the total answer? This is simple for unsigned
  156.              multiplication. If AH (or DX for word) is 0, then the total
  157.              answer is in AL (or AX for word). It is more complicated for
  158.              signed multiplication. Consider word multiplication. +30000 X +2
  159.              = +60000. But that's less than 65536, so it is completely
  160.              contained in AX, right? WRONG. The leftmost bit of AX contains
  161.              the sign. If the signed result is out of the range -32768 to
  162.              +32767, information about the absolute value of the number is
  163.              corrupting information about the sign of the number.  AX will
  164.              have the wrong number and the wrong sign. Only by combining AX
  165.              with DX will you get the correct answer. Similarly for byte
  166.              multiplication with AL, if the result is not in the range -128 to
  167.              +127, The leftmost (sign) bit will be corrupted, and only by
  168.              looking at AH:AL will you be able to get the correct result.
  169.  
  170.              If CF and OF are set, you need to look at both registers to
  171.              evaluate the number. You might want to do error handling, so once
  172.              again, you can have:
  173.  
  174.                       mul  bx
  175.                       jnc  go_on
  176.                       call error_handler
  177.                  go_on:
  178.  
  179.              using the same reverse logic as before (if nothing is wrong, skip
  180.              the error handler). We can also use:
  181.  
  182.                       mul  bx
  183.                       into
  184.  
  185.              if there is an INTO error handler. 
  186.  
  187.  
  188.              DIVISION
  189.  
  190.              Division operates in the same way as multiplication. Word
  191.  
  192.  
  193.  
  194.  
  195.              The PC Assembler Tutor                                         44
  196.              ______________________
  197.  
  198.              division operates on the DX:AX pair and byte division operates on
  199.              the AH:AL pair. There are two instructions, DIV for unsigned
  200.              division and IDIV for signed division. After the division:
  201.  
  202.                  byte      AL = quotient, AH = remainder
  203.                  word      AX = quotient, DX = remainder
  204.  
  205.              Both DIV and IDIV operate on BOTH registers. For bytes, they
  206.              consider AH:AL a single number. This means that AH must be set
  207.              correctly before the division or you will get an incorrect
  208.              answer. For words, they consider DX:AX a single number. This
  209.              means that DX must be set correctly before the division, or the
  210.              result will be incorrect. Why did Intel include AH and DX in the
  211.              division? Wouldn't it have been easier to use just AH (or AX for
  212.              word division) and put the quotient and remainder in the same
  213.              place? These instructions are actually designed for dividing a
  214.              long number (4 or 8 bytes). How it works is pretty slick; you'll
  215.              find out about it later in the book. 
  216.  
  217.              How do you set AH and DX correctly? For unsigned numbers, that's
  218.              easy. Make them 0:
  219.  
  220.                  mov  al, variable
  221.                  mov  ah, 0
  222.                  div  cl        ; unsigned byte division
  223.  
  224.              For signed division, set AH or DX to 0 (0000h) if it is a
  225.              positive number and set them to -1 (FFFFh) if the number is
  226.              negative. This is just standard sign extension that was covered
  227.              in the chapter on numbers. Fortunately for us, Intel has provided
  228.              instructions which do the sign extension for us. CBW (convert
  229.              byte to word) correctly extends the signed number in AL through
  230.              AH:AL. CWD (convert word to double) correctly extends the signed
  231.              number in AX through DX:AX. The code is
  232.  
  233.                  mov  ax, variable5
  234.                  cwd
  235.                  idiv bx             ; signed word division
  236.  
  237.              Of course with these two instructions you can convert a byte to a
  238.              double word.
  239.  
  240.                  mov  al, variable6
  241.                  cbw
  242.                  cwd
  243.                  idiv bx             ; signed word division
  244.  
  245.              first converting to a word, then to a double word.
  246.  
  247.              For the division program, we are going to use the multiplication
  248.              program and make some small changes. Make a copy of your
  249.              multiplication program:
  250.  
  251.                  >copy mult.asm  div.asm
  252.  
  253.              and then make the following changes:
  254.  
  255.  
  256.  
  257.  
  258.  
  259.              Chapter 6 - Multiplication and Division                        45
  260.              _______________________________________
  261.  
  262.                  MULTIPLICATION                     DIVISION
  263.  
  264.                  ; unsigned byte                    ; unsigned byte
  265.                                                     pop  ax
  266.                  pop  ax                            mov  ah, 0
  267.                  call show_regs_and_wait            call show_regs_and_wait
  268.                  mul  bl                            div  bl
  269.  
  270.  
  271.                  ; signed word                      ; signed word
  272.                                                     pop  ax
  273.                  pop  ax                            cwd
  274.                  call show_regs_and_wait            call show_regs_and_wait
  275.                  imul bx                            idiv bx
  276.  
  277.              The calls to print_unsigned and print_signed_4byte are
  278.              irrelevant, so you may either delete them or ignore the output.
  279.              All we did was change the multiplication instruction to division
  280.              and prepare the upper register correctly (AH for byte, DX for
  281.              word). That's all. 
  282.  
  283.              Assemble, link, and run it. Try out both positive and negative
  284.              numbers and see what the remainder looks like. Also notice the
  285.              sign extension just before the division. Remember, for division,
  286.              the results are in the following places:
  287.  
  288.                  byte      AL = quotient, AH = remainder
  289.                  word      AX = quotient, DX = remainder
  290.  
  291.              Now divide by 0. Ka-pow! You should have exited the program and
  292.              gotten an error message. Unlike the other arithmetical errors
  293.              where you have the option of ignoring them or making an error
  294.              handler for them, the 8086 considers division by 0 a major no-no.
  295.              When the 8086 detects division by zero,{1} it interrupts the
  296.              program and goes to the zero-divide handler (which is external to
  297.              the program). Normally, this just exits the program since the
  298.              data is now worthless.
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.              ____________________
  306.  
  307.              1 What it actually detects is that the quotient is too large to
  308.              fit in the lower register (AL for byte or AX for word). As long
  309.              as the upper register is correctly sign extended, the only time
  310.              this can happen is when you divide by 0. If the upper register is
  311.              NOT sign extended correctly, you can have zero divide errors all
  312.              over the place, even though you aren't dividing by 0. As an
  313.              example, if AH:AL contain 3275 and bl contains 10, then:
  314.  
  315.                  div  bl
  316.  
  317.              will give a quotient of 327 ( > 255) and will generate a zero
  318.              divide error.
  319.  
  320.  
  321.  
  322.  
  323.              The PC Assembler Tutor                                         46
  324.              ______________________
  325.  
  326.                                           SUMMARY
  327.  
  328.              MUL and IMUL
  329.                  MUL performs unsigned multiplication and IMUL performs
  330.                  signed multiplication. For bytes, the multiplicand is in AL
  331.                  and the result is in the AH:AL pair. For words, the
  332.                  multiplicand is in AX and the result is in the DX:AX pair.
  333.                  If the total result is contained in the lower register, CF
  334.                  and OF are cleared (0). If part of the result is in the
  335.                  upper register, CF and OF are set (1). The multiplier may be
  336.                  either a register or a variable in memory.
  337.  
  338.                       variable1 db ?
  339.                       variable2 dw ?
  340.  
  341.                            mul  variable1      ; unsigned byte
  342.                            mul  cx             ; unsigned word
  343.                            imul bl             ; signed byte
  344.                            imul variable2      ; signed word
  345.  
  346.  
  347.              DIV and IDIV
  348.                  DIV performs unsigned division. IDIV performs signed
  349.                  division. For bytes, the dividend is the AH:AL pair. For
  350.                  words, the dividend is the DX:AX pair. In byte division, AH
  351.                  must be correctly prepared before the division. For word
  352.                  division, DX must be correctly prepared before the division.
  353.                  The divisor may be either a register or a variable in
  354.                  memory.
  355.  
  356.                       variable1 db ?
  357.                       variable2 dw ?
  358.  
  359.                            div  variable1      ; unsigned byte
  360.                            div  cx             ; unsigned word
  361.                            idiv bl             ; signed byte
  362.                            idiv variable2      ; signed word
  363.  
  364.                  The quotient and remainder are as follows:
  365.  
  366.                       byte      AL = quotient, AH = remainder
  367.                       word      AX = quotient, DX = remainder
  368.  
  369.                  No flags are affected. If the quotient is too large for the
  370.                  lower register, or if you divide by zero, a zero divide
  371.                  program interrupt occurs.
  372.  
  373.              CORRECT SIGN EXTENSION
  374.                  To prepare for division, you must correctly sign extend the
  375.                  lower register into the upper register. For unsigned
  376.                  division, zero the upper register (AH = 0 or DX = 0). For
  377.                  signed division, use CBW and CWD. CBW (convert byte to word)
  378.                  extends a signed number in AL through AH:AL. CWD (convert
  379.                  word to double) extends a signed number in AX through DX:AX
  380.  
  381.